package com.bbex.controller;

import com.bbex.config.sercurity.RedisSessionUser;
import com.bbex.constant.Constants;
import com.bbex.constant.SercurityConstant;
import com.bbex.entity.Coin;
import com.bbex.entity.PlatUser;
import com.bbex.entity.WithdrawLog;
import com.bbex.enums.CoinTypeEnum;
import com.bbex.enums.UserVerifiEnum;
import com.bbex.enums.VerificationCodeType;
import com.bbex.enums.WithdrawStatusEnum;
import com.bbex.exception.PlatException;
import com.bbex.google.GoogleAuthenticator;
import com.bbex.pojo.GlobalMessageResponseVo;
import com.bbex.service.*;
import com.bbex.util.JsonUtils;
import com.bbex.util.RsaUtils;
import com.bbex.vo.WithdrawListVO;
import com.bbex.vo.WithdrawVO;
import com.bbex.vo.WithdrawValidateVO;
import com.bbex.valid.ValidateFiled;
import com.bbex.valid.ValidateGroup;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 用户coin转出相关操作
 */
@RestController
@RequestMapping("/bbuni")
public class WithdrawController {

    @Autowired
    private WithdrawLogService withdrawLogService;
    @Autowired
    private CoinService coinService;
    @Autowired
    private SmsMessageService smsMessageService;
    @Autowired
    private PlatUserService platUserService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;
    @Autowired
    private MessageSendService messageSendService;
    /**
     * 用户转出
     *
     * @param withdrawVO
     * @return
     */
    /*@PostMapping("/coin/volume/open/withdraw")
    @ValidateGroup(fileds = {
            @ValidateFiled(index = 0, filedName = "coinId", notNull = true, errMsg = "coinId不能为空"),
            @ValidateFiled(index = 0, filedName = "symbol", notNull = true, errMsg = "币种不能为空")
    })
    public GlobalMessageResponseVo openWithDraw(WithdrawVO withdrawVO) {

        Coin coin  = coinService.findById(withdrawVO.getCoinId());
        if(null != coin && coin.getCoinType().equals(CoinTypeEnum.EOS.getCode())){
            return GlobalMessageResponseVo
                    .newSuccessInstance((Object) "1");

        }else{
            return GlobalMessageResponseVo
                    .newSuccessInstance((Object) "0");
        }

    }*/
    /**
     * 用户转出
     *
     * @param withdrawVO
     * @return
     */
    @PostMapping("/coin/volume/withdraw")
    @ValidateGroup(fileds = {
            @ValidateFiled(index = 0, filedName = "coinId", notNull = true, errMsg = "coinId不能为空"),
            @ValidateFiled(index = 0, filedName = "symbol", notNull = true, errMsg = "币种不能为空"),
            @ValidateFiled(index = 0, filedName = "address", notNull = true, errMsg = "提币地址不能为空", maxLen = 64),
            @ValidateFiled(index = 0, filedName = "volume", notNull = true, errMsg = "提币数量不能为空")
    })
    public Mono<GlobalMessageResponseVo> withDraw(WithdrawVO withdrawVO) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();

        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    final boolean lockTrade = e.isLockTrade();
                    if (lockTrade) {
                        return GlobalMessageResponseVo.newErrorInstance(RedisSessionUser.LOCK_TIP_MESSAGE);
                    }

                    Coin coin  = coinService.findById(withdrawVO.getCoinId());
                    if(Objects.isNull(coin) || !coin.getName().equals(withdrawVO.getSymbol())){
                        return GlobalMessageResponseVo.newErrorInstance("参数异常");
                    }

                    WithdrawLog withdrawLog = new WithdrawLog();
                    BeanUtils.copyProperties(withdrawVO, withdrawLog);
                    withdrawLog.setUserId(e.getId());
                    withdrawLog.setCoinSymbol(withdrawVO.getSymbol());
                    withdrawLog.setConfirmStatus(0);
                    withdrawLog.setVersion(0L);
                    String id = withdrawLogService.save(withdrawLog);
                    return GlobalMessageResponseVo.newSuccessInstance((Object) id);
                    //withdrawLogService.updateStatusById(e.getId(), WithdrawStatusEnum.INIT.getCode(), id);

                });
    }

    /**
     * 二次确认
     *
     * @param withdrawValidateVO
     * @return
     */
    @PostMapping("/coin/volume/withdraw/validate")
    public Mono<GlobalMessageResponseVo> withDrawValidate(WithdrawValidateVO withdrawValidateVO) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();

        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    String userId = e.getId();
                    //验证邮箱
                    //messageSendService.mailValid("withdraw", VerificationCodeType.WITHDRAW_CODE, e.getMail(), withdrawValidateVO.getEmailCode());
                    //验证手机验证码
                    if(!StringUtils.isBlank(e.getMobile())){
                        smsMessageService.validSmsCode(e.getMobile(), UserVerifiEnum.USER_EX_MOBILE.getCode(), withdrawValidateVO.getValidCode());
                    }else if(!StringUtils.isBlank(e.getMail())){
                        messageSendService.mailValid(UserVerifiEnum.USER_EX_MOBILE.getCode(), VerificationCodeType.EX_TRADE_MOBILE, e.getMail(), withdrawValidateVO.getValidCode());
                    }else{
                        return GlobalMessageResponseVo.newErrorInstance("交易验证失败");

                    }

                    PlatUser user = platUserService.findByid(userId);
                    //交易密码
                    if(StringUtils.isBlank(user.getExPassword())) {
                        return GlobalMessageResponseVo.newInstance(Constants.EX_PASSWORD,"请设置交易密码");
                    }
                    String decryPassword = RsaUtils.decryptByPrivateKey(withdrawValidateVO.getExCode(), RsaUtils.DEFAULT_PRIVATE_KEY);
                    if(StringUtils.isBlank(decryPassword)) {
                        return GlobalMessageResponseVo.newErrorInstance("请填写交易密码");
                    }
                    if(!passwordEncoder.matches(decryPassword, user.getExPassword())) {
                        return GlobalMessageResponseVo.newErrorInstance("交易密码不正确");
                    }
                    //设置交易密码验证码2小时失效
                    String authKeyEx = SercurityConstant.AUTH_USERNAME_REDIS_NAMESAPCE+"ex:" + e.getUsername();
                    valOpsStr.set(authKeyEx, SercurityConstant.AuthType.PASS_AUTH.getCode(), SercurityConstant.REDIS_EXPIRE_TIME_ONE_HOUR * 2, TimeUnit.SECONDS);

                    //return GlobalMessageResponseVo.newSuccessInstance("交易验证成功");
                    withdrawLogService.updateStatusById(userId, WithdrawStatusEnum.INIT.getCode(), withdrawValidateVO.getId());

                    return GlobalMessageResponseVo.newSuccessInstance("转出成功");
                });
    }

    /**
     * 提现取消
     *
     * @param id 主键id
     * @return
     */
    @GetMapping("/coin/volume/cancel/{id}")
    public Mono<GlobalMessageResponseVo> withDrawCancel(@PathVariable("id") String id) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();

        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    String userId = e.getId();
                    withdrawLogService.withDrawCancel(userId, id);
                    return GlobalMessageResponseVo
                            .newSuccessInstance("操作成功！");
                });
    }

    /**
     * 提现列表
     *
     * @param
     * @return
     */
    @PostMapping("/coin/withdraw/list")
    public Mono<GlobalMessageResponseVo> withDrawList(WithdrawListVO withdrawListVO) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();


        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    String userId = e.getId();
                    withdrawListVO.setUserId(userId);
                    return GlobalMessageResponseVo.newSuccessInstance(withdrawLogService.findPage(withdrawListVO));

                });
    }

    /**
     * 提现详情
     *
     * @param
     * @return
     */
//    @GetMapping("/coin/withdraw/list/{id}")
//    public Mono<GlobalMessageResponseVo> withDrawDetail(@PathVariable("id") String id) {
//
//        Mono<SecurityContext> context
//                = ReactiveSecurityContextHolder.getContext();
//
//        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
//                .map(s -> s.getAuthentication().getPrincipal())
//                .cast(RedisSessionUser.class)
//                .map(e -> {
//                    String userId = e.getId();
//                    return GlobalMessageResponseVo.newSuccessInstance(withdrawLogService.findById(id));
//                });
//    }


}
